/**
 * Copyright (C) 2025 pony working team
 * SPDX-License-Identifier: MulanPSL-2.0
 */

/* includes (local) ----------------------------------------------------------*/
#include <cmsis_os.h>
/* includes (standard library, system) ---------------------------------------*/
#include <string.h>
/* includes (other library) --------------------------------------------------*/
/* includes (project) --------------------------------------------------------*/
#include <x_config.h>
#include <x_it.h>

#include <k_task.h>
#include <k_mutex.h>
#include <k_sem.h>

#ifdef CONFIG_SOFT_TIMER
#include <k_timer.h>
#endif

#ifdef CONFIG_IPC_MQ
#include <k_mq.h>
#endif

/* defines -------------------------------------------------------------------*/

#define KERNEL_UNLOCKED 0
#define KERNEL_LOCKED   1

#define OS_PRIORITY_WIN 10

#define KERNEL_ID "pony"

/* typedefs ------------------------------------------------------------------*/
/* macro ---------------------------------------------------------------------*/
/* variables (extern) --------------------------------------------------------*/
/* variables (local) ---------------------------------------------------------*/

static const osVersion_t s_osVersion = {00000001, 00000001};

/* Kernel initialization state */
static osKernelState_t s_kernelState = osKernelInactive;

/* variables (global) --------------------------------------------------------*/
/* inlines -------------------------------------------------------------------*/
/* functions -----------------------------------------------------------------*/

/// Initialize the RTOS Kernel.
/// \return status code that indicates the execution status of the function.
osStatus_t osKernelInitialize(void)
{
    if (it_context()) {
        return osErrorISR;
    }
    s_kernelState = osKernelReady;

    return osOK;
}

///  Get RTOS Kernel Information.
/// \param[out]    version       pointer to buffer for retrieving version information.
/// \param[out]    id_buf        pointer to buffer for retrieving kernel identification string.
/// \param[in]     id_size       size of buffer for kernel identification string.
/// \return status code that indicates the execution status of the function.
osStatus_t osKernelGetInfo(osVersion_t *version, char *id_buf, uint32_t id_size)
{
    if ((version == NULL) || (id_buf == NULL) || (id_size < sizeof(KERNEL_ID))) {
        return osErrorParameter;
    }
    memcpy(id_buf, KERNEL_ID, sizeof(KERNEL_ID));

    version->api = s_osVersion.api;
    version->kernel = s_osVersion.kernel;

    return osOK;
}

/// Get the current RTOS Kernel state.
/// \return current RTOS Kernel state.
osKernelState_t osKernelGetState(void)
{
    if (!task_sched_is_started()) {
        if (s_kernelState == osKernelReady) {
            return osKernelReady;
        } else {
            return osKernelInactive;
        }
    } else if (task_lock_count() > 0) {
        return osKernelLocked;
    } else {
        return osKernelRunning;
    }
}

/// Start the RTOS Kernel scheduler.
/// \return status code that indicates the execution status of the function.
osStatus_t osKernelStart(void)
{
    if (it_context()) {
        return osErrorISR;
    }
    if (s_kernelState != osKernelReady) {
        return osError;
    }

    s_kernelState = osKernelRunning;
    return osOK;
}

/// Lock the RTOS Kernel scheduler.
/// \return previous lock state (1 - locked, 0 - not locked, error code if negative).
int32_t osKernelLock(void)
{
    int32_t lock;

    if (it_context()) {
        return (int32_t)osErrorISR;
    }

    if (!task_sched_is_started()) {
        return (int32_t)osError;
    }

    if (task_lock_count() > 0) {
        lock = KERNEL_LOCKED;
    } else {
        task_lock();
        lock = KERNEL_UNLOCKED;
    }

    return lock;
}

/// Unlock the RTOS Kernel scheduler.
/// \return previous lock state (1 - locked, 0 - not locked, error code if negative).
int32_t osKernelUnlock(void)
{
    int32_t lock;

    if (it_context()) {
        return (int32_t)osErrorISR;
    }

    if (!task_sched_is_started()) {
        return (int32_t)osError;
    }

    if (task_lock_count() > 0) {
        task_unlock();
        if (task_lock_count() != 0) {
            return (int32_t)osError;
        }
        lock = KERNEL_LOCKED;
    } else {
        lock = KERNEL_UNLOCKED;
    }

    return lock;
}

/// Restore the RTOS Kernel scheduler lock state.
/// \param[in]     lock          lock state obtained by \ref osKernelLock or \ref osKernelUnlock.
/// \return new lock state (1 - locked, 0 - not locked, error code if negative).
int32_t osKernelRestoreLock(int32_t lock)
{
    if (it_context()) {
        return (int32_t)osErrorISR;
    }

    if (!task_sched_is_started()) {
        return (int32_t)osError;
    }

    switch (lock) {
    case KERNEL_UNLOCKED:
        task_unlock();
        if (task_lock_count() != 0) {
            break;
        }
        return KERNEL_UNLOCKED;
    case KERNEL_LOCKED:
        task_lock();
        return KERNEL_LOCKED;
    default:
        break;
    }

    return (int32_t)osError;
}

/// Suspend the RTOS Kernel scheduler.
/// \return time in ticks, for how long the system can sleep or power-down.
uint32_t osKernelSuspend(void)
{
    return 0;
}

/// Resume the RTOS Kernel scheduler.
/// \param[in]     sleep_ticks   time in ticks for how long the system was in sleep or power-down
/// mode.
void osKernelResume(uint32_t sleep_ticks)
{
}

/// Protect the RTOS Kernel scheduler access.
/// \param[in]     safety_class  safety class.
/// \return status code that indicates the execution status of the function.
osStatus_t osKernelProtect(uint32_t safety_class)
{
    return osError;
}

/// Destroy objects for specified safety classes.
/// \param[in]     safety_class  safety class.
/// \param[in]     mode          safety mode.
/// \return status code that indicates the execution status of the function.
osStatus_t osKernelDestroyClass(uint32_t safety_class, uint32_t mode)
{
    return osError;
}

/// Get the RTOS kernel tick count.
/// \return RTOS kernel current tick count.
uint32_t osKernelGetTickCount(void)
{
    return tick_count_get();
}

/// Get the RTOS kernel tick frequency.
/// \return frequency of the kernel tick in hertz, i.e. kernel ticks per second.
uint32_t osKernelGetTickFreq(void)
{
    return CONFIG_SYS_TICK_HZ;
}

/// Get the RTOS kernel system timer count.
/// \return RTOS kernel current system timer count as 32-bit value.
uint32_t osKernelGetSysTimerCount(void)
{
    return (uint32_t)tick_tsc();
}

/// Get the RTOS kernel system timer frequency.
/// \return frequency of the system timer in hertz, i.e. timer ticks per second.
uint32_t osKernelGetSysTimerFreq(void)
{
    return CONFIG_SYSTEM_CORE_CLOCK;
}

//  ==== Thread Management Functions ====

/// Create a thread and add it to Active Threads.
/// \param[in]     func          thread function.
/// \param[in]     argument      pointer that is passed to the thread function as start argument.
/// \param[in]     attr          thread attributes; NULL: default values.
/// \return thread ID for reference by other functions or NULL in case of error.
osThreadId_t osThreadNew(osThreadFunc_t func, void *argument, const osThreadAttr_t *attr)
{
    task_id tid;
    uint8_t priority;
    size_t stack_size;
    const char *name = "undefined";

    if ((func == NULL) || it_context()) {
        return NULL;
    }

    if (attr != NULL) {
        if ((attr->priority < osPriorityLow3) || (attr->priority > osPriorityHigh)) {
            return NULL;
        }
        /* task priority: 1~30 */
        priority = (uint8_t)(TASK_PRIO_LOWEST - (attr->priority - OS_PRIORITY_WIN));
        stack_size = (size_t)attr->stack_size;
        name = attr->name;
    } else {
        priority = TASK_PRIO_LOWEST;
        stack_size = CONFIG_TASK_MIN_STACK_SIZE;
    }

    tid = task_spawn(name, priority, 0, stack_size, (int (*)(uintptr_t))func, (uintptr_t)argument);
    return (osThreadId_t)tid;
}

/// Get name of a thread.
/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return name as null-terminated string.
const char *osThreadGetName(osThreadId_t thread_id)
{
    task_id tid = (task_id)thread_id;
    if (tid == NULL) {
        return NULL;
    }
    return tid->name;
}

/// Get safety class of a thread.
/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return safety class of the specified thread.
uint32_t osThreadGetClass(osThreadId_t thread_id)
{
    return 0;
}

/// Get MPU protected zone of a thread.
/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return MPU protected zone of the specified thread.
uint32_t osThreadGetZone(osThreadId_t thread_id)
{
    return 0;
}

/// Return the thread ID of the current running thread.
/// \return thread ID for reference by other functions or NULL in case of error.
osThreadId_t osThreadGetId(void)
{
    return (osThreadId_t)current;
}

/// Get current thread state of a thread.
/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return current thread state of the specified thread.
osThreadState_t osThreadGetState(osThreadId_t thread_id)
{
    task_id tid = (task_id)thread_id;
    osThreadState_t state;
    unsigned int task_status;

    if ((tid == NULL) || it_context()) {
        return osThreadError;
    }

    task_status = tid->status;
    if (tid == current) {
        state = osThreadRunning;
    } else if (task_status == TASK_STATUS_READY) {
        state = osThreadReady;
    } else if (task_status & (TASK_STATUS_SUSPEND | TASK_STATUS_PEND | TASK_STATUS_DELAY)) {
        state = osThreadBlocked;
    } else if (task_status == TASK_STATUS_INVALID) {
        state = osThreadInactive;
    } else {
        state = osThreadError;
    }

    return state;
}

/// Get stack size of a thread.
/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return stack size in bytes.
uint32_t osThreadGetStackSize(osThreadId_t thread_id)
{
    task_id tid = (task_id)thread_id;
    if (tid == NULL) {
        return 0;
    }
    return (uint32_t)tid->stack_size;
}

/// Get available stack space of a thread based on stack watermark recording during execution.
/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return remaining stack space in bytes.
uint32_t osThreadGetStackSpace(osThreadId_t thread_id)
{
    task_id tid = (task_id)thread_id;
    return task_stack_space(tid);
}

/// Change priority of a thread.
/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \param[in]     priority      new priority value for the thread function.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadSetPriority(osThreadId_t thread_id, osPriority_t priority)
{
    task_id tid = (task_id)thread_id;
    uint8_t prio;
    int ret;

    if (tid == NULL) {
        return osErrorParameter;
    }
    if ((priority < osPriorityLow3) || (priority > osPriorityHigh)) {
        return osErrorParameter;
    }

    prio = (uint8_t)(TASK_PRIO_LOWEST - (priority - OS_PRIORITY_WIN));
    ret = task_prio_set(tid, prio);
    if (ret == 0) {
        return osOK;
    } else {
        return osErrorResource;
    }
}

/// Get current priority of a thread.
/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return current priority value of the specified thread.
osPriority_t osThreadGetPriority(osThreadId_t thread_id)
{
    task_id tid = (task_id)thread_id;
    uint8_t priority;

    if (tid == NULL) {
        return osPriorityError;
    }

    priority = task_prio_get(tid);
    if (priority > TASK_PRIO_LOWEST) {
        return osPriorityError;
    }

    return (osPriority_t)((TASK_PRIO_LOWEST - priority) + OS_PRIORITY_WIN);
}

/// Pass control to next thread that is in state \b READY.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadYield(void)
{
    return osError;
}

/// Suspend execution of a thread.
/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadSuspend(osThreadId_t thread_id)
{
    task_id tid = (task_id)thread_id;
    int ret = task_suspend(tid);
    return (ret == 0) ? osOK : osErrorResource;
}

/// Resume execution of a thread.
/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadResume(osThreadId_t thread_id)
{
    task_id tid = (task_id)thread_id;
    int ret = task_resume(tid);
    return (ret == 0) ? osOK : osErrorResource;
}

/// Detach a thread (thread storage can be reclaimed when thread terminates).
/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadDetach(osThreadId_t thread_id)
{
    return osError;
}

/// Wait for specified thread to terminate.
/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadJoin(osThreadId_t thread_id)
{
    return osError;
}

/// Terminate execution of current running thread.
__NO_RETURN void osThreadExit(void)
{
    task_exit();

    while (1)
        ;
}

/// Terminate execution of a thread.
/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadTerminate(osThreadId_t thread_id)
{
    task_id tid = (task_id)thread_id;
    int ret = task_delete(tid);
    return (ret == 0) ? osOK : osErrorResource;
}

/// Feed watchdog of the current running thread.
/// \param[in]     ticks         interval in kernel ticks until the thread watchdog expires, or 0 to
/// stop the watchdog
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadFeedWatchdog(uint32_t ticks)
{
    return osError;
}

/// Protect creation of privileged threads.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadProtectPrivileged(void)
{
    return osError;
}

/// Suspend execution of threads for specified safety classes.
/// \param[in]     safety_class  safety class.
/// \param[in]     mode          safety mode.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadSuspendClass(uint32_t safety_class, uint32_t mode)
{
    return osError;
}

/// Resume execution of threads for specified safety classes.
/// \param[in]     safety_class  safety class.
/// \param[in]     mode          safety mode.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadResumeClass(uint32_t safety_class, uint32_t mode)
{
    return osError;
}

/// Terminate execution of threads assigned to a specified MPU protected zone.
/// \param[in]     zone          MPU protected zone.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadTerminateZone(uint32_t zone)
{
    return osError;
}

/// Set processor affinity mask of a thread.
/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \param[in]     affinity_mask processor affinity mask for the thread.
/// \return status code that indicates the execution status of the function.
osStatus_t osThreadSetAffinityMask(osThreadId_t thread_id, uint32_t affinity_mask)
{
    return osError;
}

/// Get current processor affinity mask of a thread.
/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return current processor affinity mask of the specified thread.
uint32_t osThreadGetAffinityMask(osThreadId_t thread_id)
{
    return 0;
}

static int __task_count_get(task_id task, uintptr_t arg)
{
    uint32_t *count = (uint32_t *)arg;
    *count += 1;

    return 0;
}

/// Get number of active threads.
/// \return number of active threads.
uint32_t osThreadGetCount(void)
{
    uint32_t count = 0;
    task_foreach(__task_count_get, (uintptr_t)&count);
    return count;
}

/// Enumerate active threads.
/// \param[out]    thread_array  pointer to array for retrieving thread IDs.
/// \param[in]     array_items   maximum number of items in array for retrieving thread IDs.
/// \return number of enumerated threads.
uint32_t osThreadEnumerate(osThreadId_t *thread_array, uint32_t array_items)
{
    return 0;
}

//  ==== Thread Flags Functions ====

/// Set the specified Thread Flags of a thread.
/// \param[in]     thread_id     thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \param[in]     flags         specifies the flags of the thread that shall be set.
/// \return thread flags after setting or error code if highest bit set.
uint32_t osThreadFlagsSet(osThreadId_t thread_id, uint32_t flags)
{
    return 0;
}

/// Clear the specified Thread Flags of current running thread.
/// \param[in]     flags         specifies the flags of the thread that shall be cleared.
/// \return thread flags before clearing or error code if highest bit set.
uint32_t osThreadFlagsClear(uint32_t flags)
{
    return 0;
}

/// Get the current Thread Flags of current running thread.
/// \return current thread flags.
uint32_t osThreadFlagsGet(void)
{
    return 0;
}

/// Wait for one or more Thread Flags of the current running thread to become signaled.
/// \param[in]     flags         specifies the flags to wait for.
/// \param[in]     options       specifies flags options (osFlagsXxxx).
/// \param[in]     timeout       \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return thread flags before clearing or error code if highest bit set.
uint32_t osThreadFlagsWait(uint32_t flags, uint32_t options, uint32_t timeout)
{
    return 0;
}

//  ==== Generic Wait Functions ====

/// Wait for Timeout (Time Delay).
/// \param[in]     ticks         \ref CMSIS_RTOS_TimeOutValue "time ticks" value
/// \return status code that indicates the execution status of the function.
osStatus_t osDelay(uint32_t ticks)
{
    int ret = task_delay(ticks);
    return (ret == 0) ? osOK : osErrorResource;
}

/// Wait until specified time.
/// \param[in]     ticks         absolute time in ticks
/// \return status code that indicates the execution status of the function.
osStatus_t osDelayUntil(uint32_t ticks)
{
    uint32_t current_ticks = tick_count_get();
    if (ticks < current_ticks) {
        return osErrorParameter;
    }
    uint32_t delay_ticks = ticks - current_ticks;
    int ret = task_delay(delay_ticks);
    return (ret == 0) ? osOK : osErrorResource;
}

//  ==== Timer Management Functions ====
#ifdef CONFIG_SOFT_TIMER

/// Create and Initialize a timer.
/// \param[in]     func          function pointer to callback function.
/// \param[in]     type          \ref osTimerOnce for one-shot or \ref osTimerPeriodic for periodic
/// behavior.
/// \param[in]     argument      argument to the timer callback function.
/// \param[in]     attr          timer attributes; NULL: default values.
/// \return timer ID for reference by other functions or NULL in case of error.
osTimerId_t osTimerNew(osTimerFunc_t func, osTimerType_t type, void *argument,
                       const osTimerAttr_t *attr)
{
    timer_id timer;
    uint16_t flags;

    if (func == NULL) {
        return NULL;
    }

    if (type == osTimerOnce) {
        flags = TIMER_FLAG_ONE_SHOT;
    } else if (type == osTimerPeriodic) {
        flags = TIMER_FLAG_REPEATED;
    } else {
        return NULL;
    }
    timer = timer_create(flags, 1, (void (*)(uintptr_t))func, (uintptr_t)argument);
    return (osTimerId_t)timer;
}

/// Get name of a timer.
/// \param[in]     tim_id      timer ID obtained by \ref osTimerNew.
/// \return name as null-terminated string.
const char *osTimerGetName(osTimerId_t tim_id)
{
    return NULL;
}

/// Start or restart a timer.
/// \param[in]     tim_id      timer ID obtained by \ref osTimerNew.
/// \param[in]     ticks         \ref CMSIS_RTOS_TimeOutValue "time ticks" value of the timer.
/// \return status code that indicates the execution status of the function.
osStatus_t osTimerStart(osTimerId_t tim_id, uint32_t ticks)
{
    timer_id timer = (timer_id)tim_id;

    if (timer == NULL || ticks == 0) {
        return osErrorParameter;
    }
    timer->interval = ticks;
    int ret = timer_start(timer);
    return (ret == 0) ? osOK : osErrorResource;
}

/// Stop a timer.
/// \param[in]     tim_id      timer ID obtained by \ref osTimerNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osTimerStop(osTimerId_t tim_id)
{
    timer_id timer = (timer_id)tim_id;
    int ret = timer_stop(timer);
    return (ret == 0) ? osOK : osErrorResource;
}

/// Check if a timer is running.
/// \param[in]     tim_id      timer ID obtained by \ref osTimerNew.
/// \return 0 not running, 1 running.
uint32_t osTimerIsRunning(osTimerId_t tim_id)
{
    timer_id timer = (timer_id)tim_id;

    if (timer == NULL) {
        return 0;
    }
    return (timer->status == TIMER_STAT_ACTIVE);
}

/// Delete a timer.
/// \param[in]     tim_id      timer ID obtained by \ref osTimerNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osTimerDelete(osTimerId_t tim_id)
{
    timer_id timer = (timer_id)tim_id;
    int ret = timer_delete(timer);
    return (ret == 0) ? osOK : osErrorResource;
}

#endif

//  ==== Event Flags Management Functions ====

/// Create and Initialize an Event Flags object.
/// \param[in]     attr          event flags attributes; NULL: default values.
/// \return event flags ID for reference by other functions or NULL in case of error.
osEventFlagsId_t osEventFlagsNew(const osEventFlagsAttr_t *attr)
{
    return NULL;
}

/// Get name of an Event Flags object.
/// \param[in]     ef_id         event flags ID obtained by \ref osEventFlagsNew.
/// \return name as null-terminated string.
const char *osEventFlagsGetName(osEventFlagsId_t ef_id)
{
    return NULL;
}

/// Set the specified Event Flags.
/// \param[in]     ef_id         event flags ID obtained by \ref osEventFlagsNew.
/// \param[in]     flags         specifies the flags that shall be set.
/// \return event flags after setting or error code if highest bit set.
uint32_t osEventFlagsSet(osEventFlagsId_t ef_id, uint32_t flags)
{
    return osFlagsErrorResource;
}

/// Clear the specified Event Flags.
/// \param[in]     ef_id         event flags ID obtained by \ref osEventFlagsNew.
/// \param[in]     flags         specifies the flags that shall be cleared.
/// \return event flags before clearing or error code if highest bit set.
uint32_t osEventFlagsClear(osEventFlagsId_t ef_id, uint32_t flags)
{
    return osFlagsErrorResource;
}

/// Get the current Event Flags.
/// \param[in]     ef_id         event flags ID obtained by \ref osEventFlagsNew.
/// \return current event flags.
uint32_t osEventFlagsGet(osEventFlagsId_t ef_id)
{
    return osFlagsErrorResource;
}

/// Wait for one or more Event Flags to become signaled.
/// \param[in]     ef_id         event flags ID obtained by \ref osEventFlagsNew.
/// \param[in]     flags         specifies the flags to wait for.
/// \param[in]     options       specifies flags options (osFlagsXxxx).
/// \param[in]     timeout       \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return event flags before clearing or error code if highest bit set.
uint32_t osEventFlagsWait(osEventFlagsId_t ef_id, uint32_t flags, uint32_t options,
                          uint32_t timeout)
{
    return osFlagsErrorResource;
}

/// Delete an Event Flags object.
/// \param[in]     ef_id         event flags ID obtained by \ref osEventFlagsNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osEventFlagsDelete(osEventFlagsId_t ef_id)
{
    return osErrorResource;
}

//  ==== Mutex Management Functions ====

/// Create and Initialize a Mutex object.
/// \param[in]     attr          mutex attributes; NULL: default values.
/// \return mutex ID for reference by other functions or NULL in case of error.
osMutexId_t osMutexNew(const osMutexAttr_t *attr)
{
    mutex_id id = mutex_create();
    return (osMutexId_t)id;
}

/// Get name of a Mutex object.
/// \param[in]     mut_id      mutex ID obtained by \ref osMutexNew.
/// \return name as null-terminated string.
const char *osMutexGetName(osMutexId_t mut_id)
{
    return NULL;
}

/// Acquire a Mutex or timeout if it is locked.
/// \param[in]     mut_id      mutex ID obtained by \ref osMutexNew.
/// \param[in]     timeout       \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return status code that indicates the execution status of the function.
osStatus_t osMutexAcquire(osMutexId_t mut_id, uint32_t timeout)
{
    mutex_id id = (mutex_id)mut_id;
    int ret = mutex_timedlock(id, timeout);
    return (ret == 0) ? osOK : osErrorResource;
}

/// Release a Mutex that was acquired by \ref osMutexAcquire.
/// \param[in]     mut_id      mutex ID obtained by \ref osMutexNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osMutexRelease(osMutexId_t mut_id)
{
    mutex_id id = (mutex_id)mut_id;
    int ret = mutex_unlock(id);
    return (ret == 0) ? osOK : osErrorResource;
}

/// Get Thread which owns a Mutex object.
/// \param[in]     mut_id      mutex ID obtained by \ref osMutexNew.
/// \return thread ID of owner thread or NULL when mutex was not acquired.
osThreadId_t osMutexGetOwner(osMutexId_t mut_id)
{
    mutex_id id = (mutex_id)mut_id;
    if (id == NULL) {
        return NULL;
    }
    return (osThreadId_t)(id->owner);
}

/// Delete a Mutex object.
/// \param[in]     mut_id      mutex ID obtained by \ref osMutexNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osMutexDelete(osMutexId_t mut_id)
{
    mutex_id id = (mutex_id)mut_id;
    int ret = mutex_destroy(id);
    return (ret == 0) ? osOK : osErrorResource;
}

//  ==== Semaphore Management Functions ====

/// Create and Initialize a Semaphore object.
/// \param[in]     max_count     maximum number of available tokens.
/// \param[in]     initial_count initial number of available tokens.
/// \param[in]     attr          semaphore attributes; NULL: default values.
/// \return semaphore ID for reference by other functions or NULL in case of error.
osSemaphoreId_t osSemaphoreNew(uint32_t max_count, uint32_t initial_count,
                               const osSemaphoreAttr_t *attr)
{
    sem_id id = sem_create(initial_count);
    return (osSemaphoreId_t)id;
}

/// Get name of a Semaphore object.
/// \param[in]     semaphore_id  semaphore ID obtained by \ref osSemaphoreNew.
/// \return name as null-terminated string.
const char *osSemaphoreGetName(osSemaphoreId_t semaphore_id)
{
    return NULL;
}

/// Acquire a Semaphore token or timeout if no tokens are available.
/// \param[in]     semaphore_id  semaphore ID obtained by \ref osSemaphoreNew.
/// \param[in]     timeout       \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return status code that indicates the execution status of the function.
osStatus_t osSemaphoreAcquire(osSemaphoreId_t semaphore_id, uint32_t timeout)
{
    sem_id id = (sem_id)semaphore_id;
    int ret = sem_timedwait(id, timeout);
    return (ret == 0) ? osOK : osErrorResource;
}

/// Release a Semaphore token up to the initial maximum count.
/// \param[in]     semaphore_id  semaphore ID obtained by \ref osSemaphoreNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osSemaphoreRelease(osSemaphoreId_t semaphore_id)
{
    sem_id id = (sem_id)semaphore_id;
    int ret = sem_post(id);
    return (ret == 0) ? osOK : osErrorResource;
}

/// Get current Semaphore token count.
/// \param[in]     semaphore_id  semaphore ID obtained by \ref osSemaphoreNew.
/// \return number of tokens available.
uint32_t osSemaphoreGetCount(osSemaphoreId_t semaphore_id)
{
    sem_id id = (sem_id)semaphore_id;
    if (id == NULL) {
        return 0;
    }
    return (uint32_t)sem_getvalue(id);
}

/// Delete a Semaphore object.
/// \param[in]     semaphore_id  semaphore ID obtained by \ref osSemaphoreNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osSemaphoreDelete(osSemaphoreId_t semaphore_id)
{
    sem_id id = (sem_id)semaphore_id;
    int ret = sem_destroy(id);
    return (ret == 0) ? osOK : osErrorResource;
}

//  ==== Memory Pool Management Functions ====

/// Create and Initialize a Memory Pool object.
/// \param[in]     block_count   maximum number of memory blocks in memory pool.
/// \param[in]     block_size    memory block size in bytes.
/// \param[in]     attr          memory pool attributes; NULL: default values.
/// \return memory pool ID for reference by other functions or NULL in case of error.
osMemoryPoolId_t osMemoryPoolNew(uint32_t block_count, uint32_t block_size,
                                 const osMemoryPoolAttr_t *attr)
{
    return NULL;
}

/// Get name of a Memory Pool object.
/// \param[in]     mp_id         memory pool ID obtained by \ref osMemoryPoolNew.
/// \return name as null-terminated string.
const char *osMemoryPoolGetName(osMemoryPoolId_t mp_id)
{
    return NULL;
}

/// Allocate a memory block from a Memory Pool.
/// \param[in]     mp_id         memory pool ID obtained by \ref osMemoryPoolNew.
/// \param[in]     timeout       \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return address of the allocated memory block or NULL in case of no memory is available.
void *osMemoryPoolAlloc(osMemoryPoolId_t mp_id, uint32_t timeout)
{
    return NULL;
}

/// Return an allocated memory block back to a Memory Pool.
/// \param[in]     mp_id         memory pool ID obtained by \ref osMemoryPoolNew.
/// \param[in]     block         address of the allocated memory block to be returned to the memory
/// pool.
/// \return status code that indicates the execution status of the function.
osStatus_t osMemoryPoolFree(osMemoryPoolId_t mp_id, void *block)
{
    return osErrorResource;
}

/// Get maximum number of memory blocks in a Memory Pool.
/// \param[in]     mp_id         memory pool ID obtained by \ref osMemoryPoolNew.
/// \return maximum number of memory blocks.
uint32_t osMemoryPoolGetCapacity(osMemoryPoolId_t mp_id)
{
    return 0;
}

/// Get memory block size in a Memory Pool.
/// \param[in]     mp_id         memory pool ID obtained by \ref osMemoryPoolNew.
/// \return memory block size in bytes.
uint32_t osMemoryPoolGetBlockSize(osMemoryPoolId_t mp_id)
{
    return 0;
}

/// Get number of memory blocks used in a Memory Pool.
/// \param[in]     mp_id         memory pool ID obtained by \ref osMemoryPoolNew.
/// \return number of memory blocks used.
uint32_t osMemoryPoolGetCount(osMemoryPoolId_t mp_id)
{
    return 0;
}

/// Get number of memory blocks available in a Memory Pool.
/// \param[in]     mp_id         memory pool ID obtained by \ref osMemoryPoolNew.
/// \return number of memory blocks available.
uint32_t osMemoryPoolGetSpace(osMemoryPoolId_t mp_id)
{
    return 0;
}

/// Delete a Memory Pool object.
/// \param[in]     mp_id         memory pool ID obtained by \ref osMemoryPoolNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osMemoryPoolDelete(osMemoryPoolId_t mp_id)
{
    return osErrorResource;
}

//  ==== Message Queue Management Functions ====
#ifdef CONFIG_IPC_MQ

/// Create and Initialize a Message Queue object.
/// \param[in]     msg_count     maximum number of messages in queue.
/// \param[in]     msg_size      maximum message size in bytes.
/// \param[in]     attr          message queue attributes; NULL: default values.
/// \return message queue ID for reference by other functions or NULL in case of error.
osMessageQueueId_t osMessageQueueNew(uint32_t msg_count, uint32_t msg_size,
                                     const osMessageQueueAttr_t *attr)
{
    mq_id id = mq_create(msg_count, msg_size, 0);
    return (osMessageQueueId_t)id;
}

/// Get name of a Message Queue object.
/// \param[in]     msg_q_id      message queue ID obtained by \ref osMessageQueueNew.
/// \return name as null-terminated string.
const char *osMessageQueueGetName(osMessageQueueId_t msg_q_id)
{
    return NULL;
}

/// Put a Message into a Queue or timeout if Queue is full.
/// \param[in]     msg_q_id       message queue ID obtained by \ref osMessageQueueNew.
/// \param[in]     msg_ptr       pointer to buffer with message to put into a queue.
/// \param[in]     msg_prio      message priority.
/// \param[in]     timeout       \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return status code that indicates the execution status of the function.
osStatus_t osMessageQueuePut(osMessageQueueId_t msg_q_id, const void *msg_ptr, uint8_t msg_prio,
                             uint32_t timeout)
{
    mq_id id = (mq_id)msg_q_id;
    if (id == NULL || msg_ptr == NULL) {
        return osErrorParameter;
    }
    int ret = mq_timedsend(id, (void *)msg_ptr, -1, timeout);
    return (ret == 0) ? osOK : osErrorResource;
}

/// Get a Message from a Queue or timeout if Queue is empty.
/// \param[in]     msg_q_id       message queue ID obtained by \ref osMessageQueueNew.
/// \param[out]    msg_ptr       pointer to buffer for message to get from a queue.
/// \param[out]    msg_prio      pointer to buffer for message priority or NULL.
/// \param[in]     timeout       \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out.
/// \return status code that indicates the execution status of the function.
osStatus_t osMessageQueueGet(osMessageQueueId_t msg_q_id, void *msg_ptr, uint8_t *msg_prio,
                             uint32_t timeout)
{
    mq_id id = (mq_id)msg_q_id;
    if (id == NULL || msg_ptr == NULL) {
        return osErrorParameter;
    }
    int ret = mq_timedrecv(id, msg_ptr, -1, timeout);
    return (ret == 0) ? osOK : osErrorResource;
}

/// Get maximum number of messages in a Message Queue.
/// \param[in]     msg_q_id         message queue ID obtained by \ref osMessageQueueNew.
/// \return maximum number of messages.
uint32_t osMessageQueueGetCapacity(osMessageQueueId_t msg_q_id)
{
    return 0;
}

/// Get maximum message size in a Message Queue.
/// \param[in]     msg_q_id         message queue ID obtained by \ref osMessageQueueNew.
/// \return maximum message size in bytes.
uint32_t osMessageQueueGetMsgSize(osMessageQueueId_t msg_q_id)
{
    mq_id id = (mq_id)msg_q_id;
    if (id == NULL) {
        return 0;
    }
    return (uint32_t)id->msg_size;
}

/// Get number of queued messages in a Message Queue.
/// \param[in]     msg_q_id         message queue ID obtained by \ref osMessageQueueNew.
/// \return number of queued messages.
uint32_t osMessageQueueGetCount(osMessageQueueId_t msg_q_id)
{
    mq_id id = (mq_id)msg_q_id;
    if (id == NULL) {
        return 0;
    }
    return (uint32_t)id->max_msgs;
}

/// Get number of available slots for messages in a Message Queue.
/// \param[in]     msg_q_id         message queue ID obtained by \ref osMessageQueueNew.
/// \return number of available slots for messages.
uint32_t osMessageQueueGetSpace(osMessageQueueId_t msg_q_id)
{
    return 0;
}

/// Reset a Message Queue to initial empty state.
/// \param[in]     msg_q_id         message queue ID obtained by \ref osMessageQueueNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osMessageQueueReset(osMessageQueueId_t msg_q_id)
{
    return osErrorResource;
}

/// Delete a Message Queue object.
/// \param[in]     msg_q_id         message queue ID obtained by \ref osMessageQueueNew.
/// \return status code that indicates the execution status of the function.
osStatus_t osMessageQueueDelete(osMessageQueueId_t msg_q_id)
{
    mq_id id = (mq_id)msg_q_id;
    int ret = mq_delete(id);
    return (ret == 0) ? osOK : osErrorResource;
}

#endif

//  ==== Handler Functions ====

/// Handler for expired thread watchdogs.
/// \param[in]     thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId.
/// \return new watchdog reload value or 0 to stop the watchdog.
uint32_t osWatchdogAlarm_Handler(osThreadId_t thread_id)
{
    return 0;
}

// ==== Zone Management Function ====

/// Setup MPU protected zone (called when zone changes).
/// \param[in]     zone          zone number.
void osZoneSetup_Callback(uint32_t zone)
{
}

//  ==== Exception Faults ====

/// Resume normal operation when exiting exception faults
void osFaultResume(void)
{
}
